package com.book.oauth.server.user.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.book.common.api.entity.CurrentUser;
import com.book.common.api.helper.TransformHelper;
import com.book.common.api.oauth.HystrixConstant;
import com.book.common.lang.Tuple2;
import com.book.common.result.Failed;
import com.book.common.result.RestResponse;
import com.book.common.result.Success;
import com.book.common.util.GuavaCacheUtil;
import com.book.common.util.TreeUtil;
import com.book.modules.annotation.InjectionCurrentUser;
import com.book.modules.core.controller.BaseController;
import com.book.oauth.server.model.vo.ModelVo;
import com.book.oauth.server.route.entity.Route;
import com.book.oauth.server.route.vo.RouteVo;
import com.book.oauth.server.user.dto.UserDto;
import com.book.oauth.server.user.entity.User;
import com.book.oauth.server.user.service.IUserService;
import com.book.oauth.server.user.vo.CurrentUserDetail;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.io.UnsupportedEncodingException;
import java.util.List;

/**
 * Description：
 *
 * @Author： leo.xiong
 * @CreateDate： 2019/10/11 17:43
 * @Email： leo.xiong@suyun360.com
 * Version：1.0
 */
@RestController
@Slf4j
@RequestMapping("${adminPath}")
public class AuthUserController extends BaseController {
    @Autowired
    private ConsumerTokenServices consumerTokenServices;

    @Autowired
    private IUserService userService;

    /**
     * 根据token获取登录用户主体相关信息（用户名，token，角色。。。等）
     *
     * @param token
     * @return
     */
    @PostMapping("/principal")
    @ResponseBody
    @ApiImplicitParams({
            @ApiImplicitParam(name = HystrixConstant.BOOK_TOKEN, value = HystrixConstant.BOOK_TOKEN, required = true),
    })
    public RestResponse<CurrentUser> getPrincipal(@RequestParam(value = HystrixConstant.BOOK_TOKEN) String token) {
        return userService.getCurrentUserByToken(token);
    }

    @PostMapping("/currentUserDetail")
    @ResponseBody
    @InjectionCurrentUser
    public RestResponse<CurrentUserDetail> getCurrentUserDetail(@ApiIgnore CurrentUser currentUser) {
        if (currentUser.getId() == null) {
            currentUser = userService.getCurrentUser(currentUser.getToken());
        }
        CurrentUserDetail currentUserDetail = new CurrentUserDetail();
        BeanUtils.copyProperties(currentUser, currentUserDetail);
        buildRouteVoList(currentUserDetail);
        return new Success<>(currentUserDetail);
    }

    /**
     * 拼装路由信息
     *
     * @param currentUserDetail
     */
    private void buildRouteVoList(CurrentUserDetail currentUserDetail) {
        Tuple2<CurrentUser, List<Route>> tuple2 = userService.buildCurrentUserInfo(currentUserDetail);
        for (Route route : tuple2._2()) {
            RouteVo routeVo = new RouteVo();
            BeanUtils.copyProperties(route, routeVo);
            if (routeVo.getModelVo() != null) {
                ModelVo modelVo = new ModelVo();
                BeanUtils.copyProperties(routeVo.getModelVo(), modelVo);
                routeVo.setModelVo(modelVo);
            }
            if (StringUtils.isNotEmpty(route.getTitle())) {
                routeVo.getMeta().put("title", route.getTitle());
            }
            if (StringUtils.isNotEmpty(route.getNoCache())) {
                routeVo.getMeta().put("noCache", route.getNoCache());
            }
            if (StringUtils.isNotEmpty(route.getIcon())) {
                routeVo.getMeta().put("icon", route.getIcon());
            }
            if (StringUtils.isNotEmpty(route.getActiveMenu())) {
                routeVo.getMeta().put("activeMenu", route.getActiveMenu());
            }
            if (StringUtils.isNotEmpty(route.getAffix())) {
                routeVo.getMeta().put("affix", route.getAffix());
            }
            routeVo.getMeta().put("roles", Lists.newArrayList(currentUserDetail.getRoleName()));
            currentUserDetail.getRouteList().add(routeVo);
            if (StringUtils.isNotEmpty(routeVo.getPermission())) {
                currentUserDetail.getPermissionList().add(route.getPermission());
            }
        }
        currentUserDetail.setRouteVoDataTree(TreeUtil.buildDataTree(currentUserDetail.getRouteList()));
    }

    /**
     * 清除token（注销登录）
     *
     * @param token
     * @return
     */
    @GetMapping("/logout")
    @ApiImplicitParams({
            @ApiImplicitParam(name = HystrixConstant.BOOK_TOKEN, value = HystrixConstant.BOOK_TOKEN, required = true),
    })
    public RestResponse logout(@RequestParam(value = HystrixConstant.BOOK_TOKEN) String token) {
        try {
            GuavaCacheUtil.remove(token);
            consumerTokenServices.revokeToken(token);
            return new Success("BOOK:OAUTH:10000", i18nHelper.get("BOOK:OAUTH:10000"));
        } catch (Exception e) {
            return new Failed("BOOK:OAUTH:10001", i18nHelper.get("BOOK:OAUTH:10001"));
        }
    }

    /**
     * 解析jwt token
     *
     * @param token
     * @return
     */
    @PostMapping("/decodeToken")
    @ResponseBody
    @ApiImplicitParams({
            @ApiImplicitParam(name = HystrixConstant.BOOK_TOKEN, value = HystrixConstant.BOOK_TOKEN, required = true),
    })
    public RestResponse decodeToken(@RequestParam(value = HystrixConstant.BOOK_TOKEN) String token) throws UnsupportedEncodingException {
        return new Success("BOOK:OAUTH:10002", i18nHelper.get("BOOK:OAUTH:10002"));
    }

    @PostMapping("/registered")
    @ResponseBody
    public RestResponse registered(@RequestParam(value = "userDto") UserDto userDto) {
        User queryUser = new User();
        queryUser.setUsername(userDto.getUsername());
        queryUser = userService.getOne(Wrappers.query(queryUser));
        if (queryUser != null) {
            return new Failed("BOOK:OAUTH:10006", i18nHelper.get("BOOK:OAUTH:10006"));
        }
        queryUser.setUsername(null);
        queryUser.setMobile(userDto.getMobile());
        queryUser = userService.getOne(Wrappers.query(queryUser));
        if (queryUser != null) {
            return new Failed("BOOK:OAUTH:10005", i18nHelper.get("BOOK:OAUTH:10005"));
        }
        try {
            userService.save(TransformHelper.transform(userDto, User.class));
            return new Success("BOOK:OAUTH:10003", i18nHelper.get("BOOK:OAUTH:10003"));
        } catch (Exception e) {
            log.error("注册失败", e);
            return new Failed("BOOK:OAUTH:10004", i18nHelper.get("BOOK:OAUTH:10004"));
        }
    }
}
